pub mod game_data;
pub mod input;

use bevy::prelude::*;

pub use game_data::*;
pub use input::*;

use crate::{
    config::{
        goods_config::{GoodsConfig, GoodsType, ToolType},
        seed_harvest::SeedHarvestConfig,
    },
    game::PlayerComponent,
    utils::world_pos_to_block_map_pos,
};

use super::{PlantingUiState, SavedGame, component::*, event::*, resource::*};

/// 是否可以操作
pub fn can_action(
    trigger: Trigger<EMouseLeftClick>,
    mut commands: Commands,
    map_select_block_query: Single<&SelectMapBlockComponent>,
    goods_list: Res<FastList>,
    goods_query: Query<(Entity, &GoodsComponent, &FastListIndexComponent)>,
) {
    let map_vis = map_select_block_query.into_inner();
    if map_vis.can == false {
        return;
    }
    let event = trigger.event();
    let pos = event.pos;
    //获取当前选择的物品
    let goods_cpt = goods_query
        .iter()
        .find(|(_, _, index)| {
            if index.index == goods_list.select_index {
                return true;
            }
            false
        })
        .map(|(entity, item, _)| (entity, item));
    //如果没有物品配置就不处理了
    if let Some((entity, goods_cpt)) = goods_cpt {
        match &goods_cpt.goods_item.goods_type {
            GoodsType::Seed(_) => {
                commands
                    .entity(entity)
                    .insert(PlantingComponent { pos: pos.into() });
            }
            GoodsType::Tool(tool) => match tool {
                ToolType::Hoe => {
                    commands.trigger(EHoeField { pos });
                }
                ToolType::WateringCan => {
                    commands.trigger(EWaterCrop { pos });
                }
                ToolType::Shovel => {
                    commands.trigger(EDelCrop { pos });
                }
                ToolType::Sickle => {
                    commands.trigger(EHarvestCrop { pos });
                }
            },
            GoodsType::Furniture(furniture) => {
                commands.trigger(EPutFurniture {
                    pos,
                    furniture_component: FurnitureComponent {
                        config: furniture.clone(),
                    },
                    is_consume: true,
                });
            }
            _ => {}
        }
    }
}

///种植作物
pub fn plant_crop(
    trigger: Trigger<EPlantCrop>,
    mut planting_map: ResMut<BlockMap>,
    // mut fast_list: ResMut<FastList>,
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) {
    let operation_data = trigger.event();
    let seed_item = &trigger.seed_item.clone();
    let texture_handle: Handle<Image> = asset_server.load(&seed_item.resource_path);
    let layout = TextureAtlasLayout::from_grid(
        UVec2::new(100, 100),
        seed_item.columns,
        seed_item.rows,
        None,
        None,
    );
    let texture_atlas_layout_handle = texture_atlas_layouts.add(layout);
    let pos: BlockMapPos = operation_data.pos.into();
    let is_mature = operation_data.curr_stages >= seed_item.stages_num - 1;
    let entity = commands
        .spawn((
            Sprite::from_atlas_image(
                texture_handle,
                TextureAtlas {
                    layout: texture_atlas_layout_handle,
                    index: operation_data.curr_stages as usize,
                },
            ),
            Transform::from_translation(pos.get_world_pos(5.)).with_scale(Vec3::splat(1.0)),
            CropComponent {
                day: operation_data.day,
                curr_stages: operation_data.curr_stages,
            },
            CropConfigComponent(seed_item.clone()),
            pos.clone(),
        ))
        .insert_if(MatureCrop, || is_mature)
        .id();
    planting_map.get_field(pos.x, pos.y).map_or_else(
        || {
            println!("尝试在一个不存在的地块上种植作物pos:x:{}y:{}", pos.x, pos.y);
        },
        |field| {
            field.set_crop(entity);
            if operation_data.is_consume {
                // fast_list.consume_goods_by_mid(seed_item.mid, 1);
            }
        },
    );
}

///删除作物
pub fn del_crop_obs(
    trigger: Trigger<EDelCrop>,
    mut planting_map: ResMut<BlockMap>,
    mut commands: Commands,
) {
    let operation_data = trigger.event();
    let pos = operation_data.pos;
    if let Some(field_date) = planting_map.get_field(pos.x, pos.y) {
        if let Some(crop_entity) = field_date.get_crop() {
            commands.entity(crop_entity).despawn();
        }
        field_date.del_crop();
    }
}

///浇水
pub fn water_crop(
    trigger: Trigger<EWaterCrop>,
    mut planting_map: ResMut<BlockMap>,
    mut commands: Commands,
) {
    let operation_data = trigger.event();
    let pos = operation_data.pos;
    let water_entity = commands
        .spawn((
            Sprite::from_color(
                Color::srgba(0.0, 0.0, 0.0, 0.3),
                Vec2 { x: 100.0, y: 100.0 },
            ),
            Transform::from_translation(pos.as_vec2().map(|pos| pos * 100. - 50.).extend(4.))
                .with_scale(Vec3::splat(1.0)),
            WaterComponent,
            BlockMapPos::new(pos),
        ))
        .id();
    planting_map.get_field(pos.x, pos.y).map_or_else(
        || {
            println!("尝试在一个不存在的地块上浇水pos:x:{}y:{}", pos.x, pos.y);
        },
        |field| {
            field.set_water(water_entity);
        },
    );
}

///开垦土地
pub fn hoe_field(
    trigger: Trigger<EHoeField>,
    mut planting_map: ResMut<BlockMap>,
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    let operation_data = trigger.event();
    let pos = operation_data.pos;
    let texture_handle = asset_server.load("texture/arable.png");
    let block_pos = BlockMapPos::new(pos);
    let entity = commands
        .spawn((
            Sprite::from_image(texture_handle),
            Transform::from_translation(block_pos.get_world_pos(3.)).with_scale(Vec3::splat(1.0)),
            FieldComponent,
            block_pos,
        ))
        .id();
    planting_map.set_field(pos.x, pos.y, entity);
}

///收割作物
pub fn harvest_crop(
    trigger: Trigger<EHarvestCrop>,
    mut block_map: ResMut<BlockMap>,
    seed_harvest_config: Res<SeedHarvestConfig>,
    crop_query: Query<(&CropComponent, &CropConfigComponent), With<MatureCrop>>,
    mut commands: Commands,
) {
    let operation_data = trigger.event();

    let pos = operation_data.pos;
    let crop_entity = block_map
        .get_field(pos.x, pos.y)
        .map_or_else(|| None, |field| field.get_crop());
    if crop_entity.is_none() {
        println!("作物实体不存在");
        return;
    }
    let crop_entity = crop_entity.unwrap();
    let crop = crop_query.get(crop_entity);
    if crop.is_err() {
        println!("作物组件不存在");
        return;
    }
    let crop = crop.unwrap();
    let mut e_modify_goods = EModifyGoods::new();
    let seed_harvest_item = seed_harvest_config.get_seed_harvest(crop.1.0.mid);
    if let Some(seed_harvest_item) = seed_harvest_item {
        for goods in seed_harvest_item.goods_list.iter() {
            e_modify_goods.add_goods(goods.goods_id, goods.goods_num);
        }
        commands.trigger(e_modify_goods);
        commands.entity(crop_entity).despawn();
    } else {
        println!("没有找到种子收获配置");
        return;
    }
    block_map.get_field(pos.x, pos.y).map_or_else(
        || {
            println!("尝试在一个不存在的地块上收割作物pos:x:{}y:{}", pos.x, pos.y);
        },
        |field| {
            field.del_crop();
        },
    );
}

//放置家具
pub fn place_furniture(
    trigger: Trigger<EPutFurniture>,
    mut planting_map: ResMut<BlockMap>,
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    let data = trigger.event();
    let pos = data.pos;
    let furniture_config = data.furniture_component.config.clone();
    let texture_handle = asset_server.load(furniture_config.resource_path);
    let block_pos = BlockMapPos::new(pos);
    let entity = commands
        .spawn((
            Sprite::from_image(texture_handle),
            Transform::from_translation(block_pos.get_world_pos(1.)),
            data.furniture_component.clone(),
            block_pos,
        ))
        .id();
    planting_map.set_furniture(pos.x, pos.y, entity);
    if data.is_consume {}
}

///修改物品事件监听
pub fn modify_goods_obs(
    trigger: Trigger<EModifyGoods>,
    goods_config: ResMut<GoodsConfig>,
    mut backpack_query: Query<(Entity, &mut GoodsComponent), With<BackpackIndexComponent>>,
    backpack_index_query: Query<(Entity, &BackpackIndexComponent), Without<GoodsComponent>>,
    mut fast_list_query: Query<
        (Entity, &mut GoodsComponent),
        (
            With<FastListIndexComponent>,
            Without<BackpackIndexComponent>,
        ),
    >,
    mut commands: Commands,
) {
    let event = trigger.event();
    event.goods_list.iter().for_each(|(mid, count, _)| {
        if let Some(goods_item) = goods_config.get_config(*mid) {
            //快捷栏有这个物品 呐么就直接加数量
            let item = fast_list_query.iter_mut().find(|(_, item)| {
                if item.goods_item.mid == goods_item.mid {
                    return true;
                }
                false
            });
            if let Some((_, mut item)) = item {
                item.count += *count as usize;
                return;
            }
            //背包有这个物品 呐么就直接加数量
            let item = backpack_query.iter_mut().find(|(_, item)| {
                if item.goods_item.mid == goods_item.mid {
                    return true;
                }
                false
            });
            if let Some((_, mut item)) = item {
                item.count += *count as usize;
                return;
            }

            //背包没有这个物品 那么就在背吧创建物品
            //backpack_index_query按index升序排列
            let mut backpack_index_query = backpack_index_query.iter().collect::<Vec<_>>();
            backpack_index_query.sort_by(|a, b| a.1.index.cmp(&b.1.index));
            let first = backpack_index_query.iter().next();
            if let Some((entity, _)) = first {
                commands.entity(*entity).insert(GoodsComponent {
                    goods_item: goods_item.clone(),
                    count: *count as usize,
                });
            } else {
                info!("背包没有空位了");
            }
        }
    });
}

pub fn updata_planting_day(
    time: Res<Time>,
    mut commands: Commands,
    mut query: Single<(&mut Text, &mut PlantingTimer), With<PlantingDayInfoText>>,
    mut planting_day: ResMut<PlantingDay>,
) {
    query.1.0.tick(time.delta());
    if query.1.0.just_finished() {
        planting_day.time += 1;
        let hour = planting_day.time / 60;
        if hour >= 24 {
            commands.trigger(ENextDay);
            planting_day.time = 0;
            planting_day.next_day();
        }
    }
}

///天数增加事件监听
pub fn next_day_obs(
    _: Trigger<ENextDay>,
    mut crop_query: Query<
        (
            Entity,
            &mut CropComponent,
            &mut Sprite,
            &BlockMapPos,
            &CropConfigComponent,
        ),
        Without<MatureCrop>,
    >,
    mut planting_day: ResMut<PlantingDay>,
    mut commands: Commands,
    mut block_map: ResMut<BlockMap>,
    water_query: Query<Entity, With<WaterComponent>>,
) {
    for (entity, mut crop, mut sprite, pos, config) in crop_query.iter_mut() {
        let field = block_map.get_field(pos.x, pos.y);
        if !field.map_or(false, |field| field.is_water()) {
            continue;
        };
        let Some(texture_atlas) = &mut sprite.texture_atlas else {
            continue;
        };
        crop.day += 1;
        if crop.day >= config.0.next_day {
            crop.day = 0;
            crop.curr_stages += 1;
        }
        if crop.curr_stages >= config.0.stages_num - 1 {
            crop.curr_stages = config.0.stages_num - 1;
            texture_atlas.index = crop.curr_stages as usize;
            commands.entity(entity).insert(MatureCrop);
        }
        texture_atlas.index = crop.curr_stages as usize;
    }
    planting_day.day += 1;
    block_map.get_all_field().iter_mut().for_each(|(_, field)| {
        field.dry();
    });
    water_query
        .iter()
        .for_each(|entity| commands.entity(entity).despawn());
}

pub fn create_map_select_block(mut commands: Commands, asset_server: Res<AssetServer>) {
    let texture_handle = asset_server.load("texture/ui/selectFrom.png");
    let font = asset_server.load("fonts/fusion-pixel.ttf");
    let select_cpt = SelectMapBlockComponent::new();
    commands
        .spawn((
            Sprite {
                image: texture_handle,
                color: select_cpt.get_colr(),
                ..Default::default()
            },
            Transform::from_translation(Vec3::new(0., 0., 6.)),
            Visibility::Hidden,
            select_cpt,
        ))
        .with_children(|p| {
            p.spawn((
                Text2d::new(""),
                TextFont {
                    font: font.clone(),
                    font_size: 16.,
                    ..default()
                },
                TextColor(Color::srgba(
                    0.0 as f32 / u8::MAX as f32,
                    111.0 as f32 / u8::MAX as f32,
                    255.0 as f32 / u8::MAX as f32,
                    1.0,
                )),
                TextLayout::new_with_justify(JustifyText::Center),
                Transform::from_translation(Vec3::new(0., 55., 1.)),
                SelectMapBlockText,
            ));
        });
}

// 鼠标位置显示选中光标
pub fn select_map_block(
    In(block_map_pos): In<Result<IVec2, String>>,
    map_select_block_query: Single<(
        &mut Transform,
        &mut Visibility,
        &mut SelectMapBlockComponent,
        &mut Sprite,
    )>,
    player_query: Single<&mut PlayerComponent>,
    select_text2d_query: Single<&mut Text2d, With<SelectMapBlockText>>,
    goods_list: Res<FastList>,
    mut planting_map: ResMut<BlockMap>,
    mature_crop_query: Query<&MatureCrop>,
    ui_state: Res<State<PlantingUiState>>,
    goods_query: Query<(&GoodsComponent, &FastListIndexComponent)>, //获取物品信息
) {
    //获取鼠标位置
    if let Ok(handle_pos) = block_map_pos {
        let player = player_query.into_inner();
        let player_pos = player.map_pos;

        //判断是否超过玩家位置周围1格
        let (mut map_tfm, mut map_vis, mut select_cpt, mut sprite) =
            map_select_block_query.into_inner();
        if *ui_state.get() != PlantingUiState::FastList {
            *map_vis = Visibility::Hidden;
            select_cpt.can(false);
            return;
        }
        if (handle_pos.x - player_pos.x).abs() > 1 || (handle_pos.y - player_pos.y).abs() > 1 {
            *map_vis = Visibility::Hidden;
            select_cpt.can(false);
            return;
        }
        let goods_cpt = goods_query
            .iter()
            .find(|(_, index)| {
                if index.index == goods_list.select_index {
                    return true;
                }
                false
            })
            .map(|(item, _)| item.clone());
        let mut vis = Visibility::Visible;
        if let Some(goods_cpt) = goods_cpt {
            let field = planting_map.get_field(handle_pos.x, handle_pos.y).cloned();
            let mut is_crop = false;
            let mut is_crop_mature = false;
            let is_field = field.is_some();
            let is_water = field
                .clone()
                .map_or(false, |field| field.get_water().is_some());

            if let Some(crop_entity) = field.map_or_else(|| None, |field| field.get_crop()) {
                is_crop_mature = mature_crop_query.get(crop_entity).is_ok();
                is_crop = true;
            };
            let is_furniture = planting_map
                .get_furniture(handle_pos.x, handle_pos.y)
                .is_some();
            match &goods_cpt.goods_item.goods_type {
                GoodsType::Seed(_config) => {
                    select_cpt.can(is_field && !is_crop);
                }
                GoodsType::Tool(tool) => match tool {
                    ToolType::Hoe => select_cpt.can(!is_field && !is_furniture),
                    ToolType::WateringCan => select_cpt.can(is_field && !is_water),
                    ToolType::Shovel => select_cpt.can(is_crop),
                    ToolType::Sickle => select_cpt.can(is_crop_mature),
                },
                GoodsType::Furniture(_furniture) => {
                    select_cpt.can(!is_field && !is_furniture);
                }
                _ => vis = Visibility::Hidden,
            }
            select_text2d_query.into_inner().0 = format!("{}", goods_cpt.goods_item.goods_type);
        } else {
            *map_vis = Visibility::Hidden;
            return;
        }
        sprite.color = select_cpt.get_colr();
        map_tfm.translation = handle_pos.as_vec2().map(|pos| pos * 100. - 50.).extend(6.);
        *map_vis = vis;
    }
}

///获取鼠标再地图的坐标
pub fn get_mouse_block_map_pos(
    camera: Single<(&Camera, &GlobalTransform)>,
    windows: Single<&Window>,
) -> Result<IVec2, String> {
    let (camera, camera_transform) = *camera;
    if let Some(pos) = windows
        .cursor_position()
        .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
        .map(|ray| ray.origin.truncate())
    {
        let handle_pos = world_pos_to_block_map_pos(&pos);
        return Ok(handle_pos);
    }
    Err("获取鼠标位置失败or转换地图块坐标失败".to_string())
}

///创建草地
pub fn spawn_grass(mut commands: Commands, asset_server: Res<AssetServer>) {
    let texture_handle = asset_server.load("texture/grass.png");
    for x in -10..=10 {
        for y in -10..=10 {
            let pos = BlockMapPos::new(IVec2::new(x, y));
            commands.spawn((
                Sprite::from_image(texture_handle.clone()),
                Transform::from_translation(pos.get_world_pos(0.)),
                GrassComponent,
                BlockMapPos::new(IVec2::new(x, y)),
            ));
        }
    }
}

///update草地
pub fn updata_grass(
    player_query: Single<&mut PlayerComponent>,
    mut grass_query: Query<(
        Entity,
        &mut GrassComponent,
        &mut BlockMapPos,
        &mut Transform,
    )>,
    mut last_player_pos: Local<IVec2>,
) {
    let player_pos = player_query.map_pos;
    if *last_player_pos == player_pos {
        return;
    }
    *last_player_pos = player_pos;
    //可视左上角坐标
    let vis_x = player_pos.x - 10;
    let vis_y = player_pos.y - 10;
    //可视右下角坐标
    let vis_x2 = player_pos.x + 10;
    let vis_y2 = player_pos.y + 10;

    grass_query.iter_mut().for_each(|(_, _, mut pos, mut tfm)| {
        let x = pos.x;
        let y = pos.y;
        let mut to_x = x;
        let mut to_y = y;
        if x < vis_x || x > vis_x2 {
            to_x = match x {
                x if x < player_pos.x => x + 21,
                x if x > vis_x2 => x - 21,
                _ => x,
            };
        }
        if y < vis_y || y > vis_y2 {
            to_y = match y {
                y if y < player_pos.y => y + 21,
                y if y > vis_y2 => y - 21,
                _ => y,
            };
        }
        pos.x = to_x;
        pos.y = to_y;
        tfm.translation = pos.get_world_pos(0.);
    });
}

pub fn set_fast_list(
    add_goods: Query<(Entity, &FastListIndexComponent), Added<FastListIndexComponent>>,
    mut fast_list: ResMut<FastList>,
) {
    add_goods.iter().for_each(|(entity, index_cpt)| {
        fast_list.entitys[index_cpt.index] = Some(entity);
    });
}

///设置背包
pub fn set_backpack(
    add_goods: Query<(Entity, &BackpackIndexComponent), Added<BackpackIndexComponent>>,
    mut backpack: ResMut<MasterBackpack>,
) {
    add_goods.iter().for_each(|(entity, index_cpt)| {
        backpack.entitys[index_cpt.index] = Some(entity);
    });
}

pub fn packback_move_fast_list(
    mut commands: Commands,
    backpack_query: Query<
        (Entity, &BackpackIndexComponent, &GoodsComponent),
        Added<BackpackMoveFastListComponent>,
    >,
    fast_list_query: Query<(Entity, &FastListIndexComponent), Without<GoodsComponent>>,
    mut backpack: ResMut<MasterBackpack>,
) {
    if backpack_query.is_empty() || fast_list_query.is_empty() {
        return;
    }
    let mut fast_list_query = fast_list_query.iter().collect::<Vec<_>>();
    fast_list_query.sort_by(|a, b| a.1.index.cmp(&b.1.index));
    backpack_query
        .iter()
        .for_each(|(entity, index_cpt, goods_config)| {
            let first = fast_list_query.iter().next();
            if let Some((fast_index_entity, _)) = first {
                backpack.entitys[index_cpt.index] = None;
                commands
                    .entity(*fast_index_entity)
                    .insert(goods_config.clone());
                commands
                    .entity(entity)
                    .remove::<(BackpackMoveFastListComponent, GoodsComponent)>();
            }
        });
}

pub fn fast_list_move_backpack(
    mut commands: Commands,
    fast_list_query: Query<
        (Entity, &FastListIndexComponent, &GoodsComponent),
        Added<FastListMoveBackpackComponent>,
    >,
    backpack_query: Query<(Entity, &BackpackIndexComponent), Without<GoodsComponent>>,
    mut fast_list: ResMut<FastList>,
) {
    if backpack_query.is_empty() || fast_list_query.is_empty() {
        return;
    }
    let mut backpack_query = backpack_query.iter().collect::<Vec<_>>();
    backpack_query.sort_by(|a, b| a.1.index.cmp(&b.1.index));
    fast_list_query
        .iter()
        .for_each(|(fast_index_entity, index_cpt, goods_config)| {
            let first = backpack_query.iter().next();
            if let Some((backpack_index_entity, _)) = first {
                fast_list.entitys[index_cpt.index] = None;
                commands
                    .entity(*backpack_index_entity)
                    .insert(goods_config.clone());
                commands
                    .entity(fast_index_entity)
                    .remove::<(FastListMoveBackpackComponent, GoodsComponent)>();
            }
        });
}

pub fn planting_crop(
    mut commands: Commands,
    mut fast_list_query: Query<
        (
            Entity,
            &mut GoodsComponent,
            &PlantingComponent,
            &FastListIndexComponent,
        ),
        Added<PlantingComponent>,
    >,
    mut fast_list: ResMut<FastList>,
) {
    for (entity, mut crop_cpt, planting, index_cpt) in fast_list_query.iter_mut() {
        let seed_item = crop_cpt.goods_item.goods_type.clone();
        if let GoodsType::Seed(seed_item) = seed_item {
            commands.trigger(EPlantCrop {
                pos: planting.pos.clone().into(),
                day: 0,
                curr_stages: 0,
                seed_item,
                is_consume: true,
            });
            crop_cpt.count -= 1;
            if crop_cpt.count <= 0 {
                fast_list.entitys[index_cpt.index] = None;
                commands.entity(entity).despawn();
            } else {
                commands.entity(entity).remove::<PlantingComponent>();
            }
        }
    }
}

pub fn first_load_game_obs(
    _: Trigger<EFirstLoadGame>,
    goods_config: Res<GoodsConfig>,
    backpack: Res<MasterBackpack>,
    fast_list: Res<FastList>,
    mut commands: Commands,
) {
    let backpack_data_list = [goods_config.get_config(0), goods_config.get_config(1)];
    let fast_data_list = [
        goods_config.get_config(4),
        goods_config.get_config(5),
        goods_config.get_config(6),
        goods_config.get_config(7),
        goods_config.get_config(8),
    ];
    for index in 0..backpack.max_count {
        let item = backpack_data_list.get(index);
        if let Some(goods_item) = item.cloned() {
            if let Some(item) = goods_item {
                commands.spawn((
                    GoodsComponent {
                        goods_item: item.clone(),
                        count: 10,
                    },
                    BackpackIndexComponent { index },
                ));
                continue;
            }
        }
        commands.spawn(BackpackIndexComponent { index });
    }
    for index in 0..fast_list.max_count {
        let item = fast_data_list.get(index);
        if let Some(goods_item) = item.cloned() {
            if let Some(item) = goods_item {
                commands.spawn((
                    GoodsComponent {
                        goods_item: item.clone(),
                        count: 1,
                    },
                    FastListIndexComponent { index },
                ));
                continue;
            }
        }
        commands.spawn(FastListIndexComponent { index });
    }
}

///快捷栏按钮点击
pub fn fast_list_click(
    // mut commands: Commands,
    query: Query<(&FastListButton, &Interaction), Changed<Interaction>>,
    mut goods_list: ResMut<FastList>,
) {
    query
        .iter()
        .for_each(|(button, interaction)| match interaction {
            Interaction::Pressed => {
                goods_list.select_index = button.index;
            }
            _ => {}
        });
}
